#!/bin/bash

# 用户系统服务压力测试执行脚本
# 使用方法: ./run-stress-test.sh [scenario_name]

set -e

# 配置变量
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
JMETER_HOME="${JMETER_HOME:-/opt/apache-jmeter}"
TEST_CONFIG="$SCRIPT_DIR/stress-test-config.json"
JMETER_SCRIPT="$SCRIPT_DIR/UserSystemService_Stress_Test.jmx"
RESULTS_DIR="$SCRIPT_DIR/results"
TIMESTAMP=$(date +"%Y%m%d_%H%M%S")

# 创建结果目录
mkdir -p "$RESULTS_DIR"

# 日志函数
log() {
    echo "[$(date +'%Y-%m-%d %H:%M:%S')] $1" | tee -a "$RESULTS_DIR/stress-test.log"
}

# 错误处理函数
handle_error() {
    log "错误: $1"
    exit 1
}

# 检查依赖
check_dependencies() {
    log "检查依赖..."

    # 检查JMeter
    if [ ! -d "$JMETER_HOME" ]; then
        handle_error "JMeter未找到，请设置JMETER_HOME环境变量或安装JMeter"
    fi

    if [ ! -f "$JMETER_HOME/bin/jmeter" ]; then
        handle_error "JMeter可执行文件未找到"
    fi

    # 检查配置文件
    if [ ! -f "$TEST_CONFIG" ]; then
        handle_error "测试配置文件未找到: $TEST_CONFIG"
    fi

    # 检查JMeter脚本
    if [ ! -f "$JMETER_SCRIPT" ]; then
        handle_error "JMeter脚本文件未找到: $JMETER_SCRIPT"
    fi

    # 检查jq（JSON处理工具）
    if ! command -v jq &> /dev/null; then
        log "警告: jq未安装，某些功能可能无法使用"
    fi

    log "依赖检查完成"
}

# 显示帮助信息
show_help() {
    cat << EOF
用户系统服务压力测试脚本

使用方法:
  $0 [选项] [场景名称]

选项:
  -h, --help          显示此帮助信息
  -l, --list         显示可用的测试场景
  -a, --all          运行所有测试场景
  -s, --scenario SCENARIO  运行指定场景
  -c, --config CONFIG  指定配置文件
  -o, --output DIR     指定输出目录
  -u, --users NUM     设置并发用户数
  -d, --duration SEC   设置测试持续时间（秒）
  -r, --report         生成详细报告
  -v, --verbose       详细输出

示例:
  $0 -l                          # 显示可用场景
  $0 -s low_load              # 运行低负载测试
  $0 -s medium_load           # 运行中等负载测试
  $0 -a                        # 运行所有场景
  $0 -s high_load -u 300 -d 600  # 自定义参数运行高负载测试

可用的测试场景:
  - low_load      低负载测试 (10并发用户, 5分钟)
  - medium_load   中等负载测试 (50并发用户, 10分钟)
  - high_load     高负载测试 (200并发用户, 15分钟)
  - extreme_load  极限负载测试 (500并发用户, 10分钟)
  - stability     稳定性测试 (100并发用户, 1小时)
  - spike        峰值冲击测试 (1000并发用户, 2分钟)

EOF
}

# 显示可用场景
list_scenarios() {
    log "可用的测试场景："

    if command -v jq &> /dev/null; then
        jq -r '.testScenarios[] | "-  \(.name): \(.description)"' "$TEST_CONFIG"
    else
        log "请安装jq工具以查看详细场景信息"
        log "可用场景: low_load, medium_load, high_load, extreme_load, stability, spike"
    fi
}

# 获取场景配置
get_scenario_config() {
    local scenario="$1"

    if command -v jq &> /dev/null; then
        jq -r ".testScenarios[] | select(.name == \"$scenario\")" "$TEST_CONFIG"
    else
        log "请安装jq工具以获取场景配置"
        return 1
    fi
}

# 运行单个场景
run_scenario() {
    local scenario="$1"
    local users="${2:-}"
    local duration="${3:-}"
    custom_users="$users"
    custom_duration="$duration"

    log "开始运行场景: $scenario"

    # 获取场景配置
    local scenario_config
    scenario_config=$(get_scenario_config "$scenario")

    if [ $? -ne 0 ]; then
        handle_error "未找到场景配置: $scenario"
    fi

    # 提取场景参数
    local concurrent_users ramp_up_time test_duration ramp_down_time think_time
    concurrent_users=$(echo "$scenario_config" | jq -r '.concurrentUsers // empty')
    ramp_up_time=$(echo "$scenario_config" | jq -r '.rampUpTime // 60')
    test_duration=$(echo "$scenario_config" | jq -r '.duration // 300')
    ramp_down_time=$(echo "$scenario_config" | jq -r '.rampDownTime // 30')
    think_time=$(echo "$scenario_config" | jq -r '.thinkTime // 2000')

    # 应用自定义参数
    if [ -n "$custom_users" ]; then
        concurrent_users="$custom_users"
    fi

    if [ -n "$custom_duration" ]; then
        test_duration="$custom_duration"
    fi

    log "场景参数:"
    log "  并发用户数: $concurrent_users"
    log "  启动时间: ${ramp_up_time}秒"
    log "  测试时间: ${test_duration}秒"
    log "  停止时间: ${ramp_down_time}秒"
    log "  思考时间: ${think_time}毫秒"

    # 创建场景结果目录
    local scenario_result_dir="$RESULTS_DIR/${scenario}_${TIMESTAMP}"
    mkdir -p "$scenario_result_dir"

    # 更新JMeter脚本中的变量
    local updated_script="$scenario_result_dir/UserSystemService_Stress_Test_${scenario}_${TIMESTAMP}.jmx"

    sed "s/\${CONCURRENT_USERS}/$concurrent_users/g" "$JMETER_SCRIPT" > "$updated_script"
    sed "s/\${RAMP_UP_TIME}/$ramp_up_time/g" "$updated_script" > temp_script && mv temp_script "$updated_script"
    sed "s/\${DURATION}/$test_duration/g" "$updated_script" > temp_script && mv temp_script "$updated_script"
    sed "s/\${RAMP_DOWN_TIME}/$ramp_down_time/g" "$updated_script" > temp_script && mv temp_script "$updated_script"
    sed "s/\${THINK_TIME}/$think_time/g" "$updated_script" > temp_script && mv temp_script "$updated_script"

    # 运行JMeter测试
    log "开始执行JMeter测试..."

    local jtl_file="$scenario_result_dir/test_results_${scenario}_${TIMESTAMP}.jtl"
    local html_report="$scenario_result_dir/report_${scenario}_${TIMESTAMP}.html"

    "$JMETER_HOME/bin/jmeter" \
        -n \
        -t "$scenario" \
        -l "$scenario_result_dir/stress_test_${scenario}.log" \
        -j "$jtl_file" \
        -e \
        -J "$scenario_result_dir/jmeter.log" \
        "$updated_script"

    local jmeter_exit_code=$?

    # 生成HTML报告
    log "生成HTML报告..."
    "$JMETER_HOME/bin/jmeter" \
        -g "$jtl_file" \
        -o "$html_report"

    # 复制配置文件到结果目录
    cp "$TEST_CONFIG" "$scenario_result_dir/"
    cp "$updated_script" "$scenario_result_dir/"

    # 记录测试结果
    log "测试完成: $scenario"
    log "结果目录: $scenario_result_dir"
    log "JTL文件: $jtl_file"
    log "HTML报告: $html_report"

    if [ $jmeter_exit_code -eq 0 ]; then
        log "场景执行成功"
    else
        log "场景执行失败，退出码: $jmeter_exit_code"
        return $jmeter_exit_code
    fi
}

# 运行所有场景
run_all_scenarios() {
    log "开始运行所有测试场景..."

    local scenarios=("low_load" "medium_load" "high_load" "extreme_load" "stability" "spike")
    local failed_scenarios=()

    for scenario in "${scenarios[@]}"; do
        log "========================================"
        log "运行场景: $scenario"
        log "========================================"

        if run_scenario "$scenario"; then
            log "场景 $scenario 执行成功"
        else
            log "场景 $scenario 执行失败"
            failed_scenarios+=("$scenario")
        fi

        # 场景间隔等待
        log "等待30秒后继续下一个场景..."
        sleep 30
    done

    # 生成汇总报告
    log "========================================"
    log "生成汇总报告"
    log "========================================"

    local summary_file="$RESULTS_DIR/stress_test_summary_${TIMESTAMP}.md"

    cat > "$summary_file" << EOF
# 用户系统服务压力测试汇总报告

**测试时间**: $(date)
**测试环境**: $BASE_URL

## 测试场景执行结果

EOF

    for scenario in "${scenarios[@]}"; do
        if [[ ! " ${failed_scenarios[*]} " =~ " ${scenario} " ]]; then
            echo "- ✅ $scenario: 成功" >> "$summary_file"
        else
            echo "- ❌ $scenario: 失败" >> "$summary_file"
        fi
    done

    cat >> "$summary_file" << EOF

## 结果文件位置

- 基础结果目录: $RESULTS_DIR
- 汇总报告: $summary_file

## 建议

1. 查看各场景的HTML报告了解详细结果
2. 分析响应时间和吞吐量指标
3. 检查错误日志和异常情况
4. 根据性能指标调整系统配置

---
EOF

    log "汇总报告已生成: $summary_file"

    if [ ${#failed_scenarios[@]} -eq 0 ]; then
        log "所有场景执行成功！"
        return 0
    else
        log "部分场景执行失败: ${failed_scenarios[*]}"
        return 1
    fi
}

# 生成详细分析报告
generate_detailed_report() {
    log "生成详细分析报告..."

    local report_file="$RESULTS_DIR/detailed_analysis_${TIMESTAMP}.md"

    cat > "$report_file" << 'EOF'
# 用户系统服务压力测试详细分析报告

## 测试概述

本次压力测试针对用户系统服务的各个核心功能模块进行了全面的性能评估，包括用户认证、用户管理、角色管理、组织架构、双因素认证、备份恢复等模块。

## 测试环境

- **测试时间**: $(date)
- **测试环境**: $(echo $BASE_URL | sed 's|^/api||')
- **测试工具**: Apache JMeter
- **测试数据**: 模拟用户数据

## 性能指标分析

### 响应时间分析

- **平均响应时间**: < 2秒（目标）
- **95%响应时间**: < 5秒（目标）
- **99%响应时间**: < 10秒（可接受）

### 吞吐量分析

- **目标吞吐量**: 500 请求/秒
- **最低吞吐量**: 100 请求/秒
- **峰值吞吐量**: 根据测试结果确定

### 错误率分析

- **最大允许错误率**: 1%
- **实际错误率**: 根据测试结果确定

### 资源使用分析

- **CPU使用率**: < 80%（目标）
- **内存使用率**: < 85%（目标）
- **磁盘使用率**: < 90%（目标）

## 测试场景结果

[各场景的详细结果将在此处展示]

## 性能瓶颈分析

[性能瓶颈分析将在此处展示]

## 优化建议

[系统优化建议将在此处展示]

## 结论

[总体结论将在此处展示]

---
报告生成时间: $(date)
EOF

    log "详细分析报告已生成: $report_file"
}

# 主函数
main() {
    # 解析命令行参数
    while [[ $# -gt 0 ]]; do
        case $1 in
            -h|--help)
                show_help
                exit 0
                ;;
            -l|--list)
                list_scenarios
                exit 0
                ;;
            -a|--all)
                check_dependencies
                run_all_scenarios
                generate_detailed_report
                exit $?
                ;;
            -s|--scenario)
                shift
                check_dependencies
                run_scenario "$1" "$2" "$3"
                exit $?
                ;;
            -c|--config)
                shift
                TEST_CONFIG="$1"
                ;;
            -o|--output)
                shift
                RESULTS_DIR="$1"
                mkdir -p "$RESULTS_DIR"
                ;;
            -u|--users)
                shift
                CUSTOM_USERS="$1"
                ;;
            -d|--duration)
                shift
                CUSTOM_DURATION="$1"
                ;;
            -r|--report)
                GENERATE_DETAILED_REPORT=true
                ;;
            -v|--verbose)
                set -x
                ;;
            *)
                log "未知参数: $1"
                show_help
                exit 1
                ;;
        esac
        shift
    done

    # 默认运行指定场景或显示帮助
    if [ -z "${SCENARIO_NAME:-}" ]; then
        show_help
    else
        check_dependencies
        run_scenario "$SCENARIO_NAME" "$CUSTOM_USERS" "$CUSTOM_DURATION"

        if [ "$GENERATE_DETAILED_REPORT" = "true" ]; then
            generate_detailed_report
        fi
    fi
}

# 执行主函数
main "$@"